#!/bin/bash
#
# passgen - create strong passwords from easy-to-remember strings
#
# This is a fork of the Password generator from the one in JXSelf's post:
#
#     https://jxself.org/password-generator.shtml
#
# In his original proposal, Jonathan suggests taking a hash of a relatively
# weak password composed of a password seed (called there a "salt") combined
# with a service-specific identifier (called a "string") and encoding it with
# base64 to produce a 32 character strong-looking password.
#
# However, it ocurred to me that perhaps these passwords may be easy to reverse
# in case it becomes known that you indeed generate your passwords using this 
# method. All the attacker has to do is realize that the password looks like a
# base64-encoded string (easy to infer from the pattern of the string).
#
# For example, suppose you use the salt "banana" and the string "example.com"
# to get the password YmFmNzc1MjQ1MWJlMWI2Y2IyNGQyNjJk. Decoding that, we get:
# baf7752451be1b6cb24d262d, a slice of the original hash. That information 
# could be used to figure out parts of the hashed string, most importantly the
# common salt used accross all passwords...
# 
# My modifications include the insertion of additional methods for making the
# reversibility harder, and the usage of more non-alphanumeric characters 
# through the usage of tr.
#
# --------
# Short history:
# 0.1-ALPHA - first usable release
# 1.0 - First version (with a new algorithm) released
# --------
#
#    Copyright (C) 2016 - kzimmermann <https://quitter.se/kzimmermann>
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

SECLEVEL=7 # How many times are tokens hashed?

while [ true ];
do
    printf "Enter your salt: "
    read -s SALT
    printf "\n"
    printf "Confirm: "
    read -s SALT_CONFIRM
    echo -en "\n"
    if [ "$SALT" == "$SALT_CONFIRM" ]; then
        break
    fi
    echo "Salts don't match. Please try again."
done
if [[ -z "$1" ]]
then
    printf "Enter your string: "
    read STRING
else
    STRING="$1"
fi

SEED="$SALT$STRING"

HASH="$SEED"

for ((i=0; i < $SECLEVEL; i++))
do
    HASH=$(printf "$HASH" | sha256sum | cut -d " " -f 1)
done

PASSWORD=$(printf "$HASH" | base64)

START=${#SEED}

if [[ -f /usr/bin/xsel ]]; then
    printf ${PASSWORD:$START:32} | xsel -ib
    echo "Password copied to the clipboard. Press enter to finish."
    read
    date '+%d-%m-%Y' | xsel -ib
else
    echo ${PASSWORD:$START:32}
    echo "Copy and press enter to finish"
    read 
    # clear screen safely so to make difficult scrolling back to read it.
    for ((i=0; i < 500; i++))
    do
        printf "\n\n\n"
    done
    clear
fi

